//////////////////////////////////////
// Fast Container Library           //
// MIT License - Copyright (c) 2012 //
//////////////////////////////////////

#pragma once

#include "common.h"
#include "bit_base.h"
#include "array_base.h"

FC_NAMESPACE_BEGIN


template <class Allocator>
class bit_array : private array_base<size_t, Allocator>
{
public:
	typedef bit_array<Allocator>				this_type;
	typedef array_base<size_t, Allocator>		base_type;
	typedef bit_reference						reference;

	enum : size_t
	{
		size_bits = 32,
		size_mask = 31,
		size_shift = 5
	};

	using base_type::swap;
	using base_type::m_data;
	using base_type::m_size;

	bit_array()
		: base_type()
		{
		}

	explicit bit_array( size_t size )
		: base_type()
		{
			resize(size);
		}

	bit_array( const this_type& x )
		: base_type(x)
		{
		}

	~bit_array()
		{
			m_size = m_size ? get_word_count(m_size) : 0;
		}

	reference operator[]( size_t pos ) { return reference( &m_data[pos >> size_shift], pos & size_mask ); }
	bool operator []( size_t pos ) const { return test(pos); }

	bool get( size_t pos ) const { return operator[](pos); }
	bool test( size_t pos ) const { return operator[](pos); }

	void flip( size_t pos ) { operator[](pos).flip(); }
	void set( size_t pos, bool value ) { operator[](pos) = value; }

	void reset()
	{
		::memset( m_data, 0, m_size * sizeof(size_t) );
	}

	void resize( size_t n )
	{
		//convert from bits to words in order to allocate the correct array size.
		size_t newSize = get_word_count(n);
		m_size = get_word_count(m_size);
		base_type::resize(newSize, 0);
		m_size = n;
	}

	size_t get_word_count( size_t bits )
	{
		return bits ? FC_INT32_WORDCOUNT(bits) : 0;
	}

	bool empty() const { return m_size == 0; }
	size_t size() const { return m_size; }

	size_t* data() { return m_data; }
	const size_t* data() const { return m_data; }

	void swap( this_type& x )
	{
		base_type::swap(x);
	}

};


FC_NAMESPACE_END
